package com.feinno.urcs.group.interop.service;

import com.feinno.urcs.dns.EnumService;
import com.feinno.urcs.group.GroupConfiguration;
import com.feinno.urcs.group.GroupError;
import com.feinno.urcs.group.GroupException;
import com.feinno.urcs.group.api.*;
import com.feinno.urcs.group.entity.*;
import com.feinno.urcs.group.interop.FXGroupManagerInterOpService;
import com.feinno.urcs.group.interop.FxDataValidateService;
import com.feinno.urcs.group.interop.entity.*;
import com.feinno.urcs.group.pctask.task.*;
import com.feinno.urcs.group.pd.task.entity.*;
import com.feinno.urcs.group.service.NotifyMembersHelper;
import com.feinno.urcs.group.service.PdNotifyMembersHelper;
import com.feinno.urcs.group.siptask.task.*;
import com.feinno.urcs.mobile.UserLocatorService;
import com.feinno.urcs.mobile.entity.UserType;
import com.feinno.urcs.profile.entity.ClientType;
import com.feinno.urcs.types.MobileNo;
import com.feinno.util.StringUtils;
import org.helium.framework.annotations.FieldSetter;
import org.helium.framework.annotations.ServiceImplementation;
import org.helium.framework.annotations.ServiceSetter;
import org.helium.framework.annotations.TaskEvent;
import org.helium.framework.rpc.LegacyRpcService;
import org.helium.framework.task.TaskProducer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.sip.address.SipURI;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author Li.Hongbo <lihongbo@feinno.com>
 */
@ServiceImplementation
@LegacyRpcService(serviceName = "GroupManagerRpc")
public class FXGroupManagerInterOpServiceImpl implements FXGroupManagerInterOpService {
	private static final Logger LOGGER = LoggerFactory.getLogger(FXGroupManagerInterOpServiceImpl.class);
	//TODO 这里按说是不需要DAO , 而应该访问缓存, 如果缓存不存在则缓存维护逻辑构造缓存.
	@ServiceSetter
	private GroupDao groupDao;
	@ServiceSetter
	private GroupService groupService;
	@ServiceSetter
	private GroupIndexService groupIndexService;
	@ServiceSetter
	private UserGroupListDao userGroupListDao;
	@ServiceSetter
	private GroupSubscriptionManager subscriptionManager;
	@ServiceSetter
	private GroupTerminalService groupTerminalService;
	@ServiceSetter(id = "urcs:EnumService")
	private EnumService enumService;

	@ServiceSetter
	private UserLocatorService userLocatorService;


	@TaskEvent(GroupTaskEvents.GROUP_INVITE)
	private TaskProducer<GroupInviteArgs> inviteJoinGroupTask;
	@TaskEvent(GroupTaskEvents.GROUP_INFO_NOTIFY)
	private TaskProducer<GroupInfoNotifyArgs> infoNotifyTask;
	@TaskEvent(GroupTaskEvents.GROUP_LIST_NOTIFY)
	private TaskProducer<GroupListNotifyArgs> listNotifyTask;
	@TaskEvent(GroupTaskEvents.GROUP_BYE)
	private TaskProducer<GroupByeArgs> byeTask;
	// And PC Server Task
	@TaskEvent(GroupTaskEvents.GROUP_INVITE_NOTIFY_TO_PC)
	private TaskProducer<AndPcGroupInviteNotifyArgs> groupInviteNotifyToPcTask;
	@TaskEvent(GroupTaskEvents.GROUP_INFO_NOTIFY_TO_PC)
	private TaskProducer<AndPcGroupInfoNotifyArgs> groupInfoNotifyToPcTask;
	@TaskEvent(GroupTaskEvents.GROUP_MEMBER_INFO_NOTIFY_TO_PC)
	private TaskProducer<AndPcGroupMemberInfoNotifyArgs> groupMemberInfoNotifyToPcTask;
	@TaskEvent(GroupTaskEvents.DISMISS_GROUP_NOTIFY_TO_PC)
	private TaskProducer<AndPcDismissGroupNotifyArgs> dismissGroupNotifyToPcTask;
	@TaskEvent(GroupTaskEvents.GROUP_LIST_NOTIFY_TO_PC)
	private TaskProducer<AndPcGroupListNotifyArgs> grouplistNotifyToPcTask;


	// PD Group Task
	@TaskEvent(GroupTaskEvents.GROUP_PD_CHANGE_ADMIN_NOTIFY)
	private TaskProducer<PdChangeGroupOwnerNotifyArgs> pdChangeGroupOwnerNotifyTask;
	@TaskEvent(GroupTaskEvents.GROUP_PD_DISMISS_NOTIFY)
	private TaskProducer<PdDeleteGroupNotifyArgs> pdDeleteGroupNotifyTask;
	@TaskEvent(GroupTaskEvents.GROUP_PD_INFO_NOTIFY)
	private TaskProducer<PdGroupInfoNotifyArgs> pdGroupInfoNotifyTask;
	@TaskEvent(GroupTaskEvents.GROUP_PD_INVITE_REPLY)
	private TaskProducer<PdGroupInviteReplyMessageArgs> pdGroupInviteReplyMessageTask;
	@TaskEvent(GroupTaskEvents.GROUP_PD_INVITE_REPLY_NOTIFY)
	private TaskProducer<PdGroupInviteReplyNotifyArgs> pdGroupInviteReplyNotifyTask;
	@TaskEvent(GroupTaskEvents.GROUP_PD_KICK_MEMBER_NOTIFY)
	private TaskProducer<PdRemoveGroupMemberNotifyArgs> pdRemoveGroupMemberNotifyTask;
	@TaskEvent(GroupTaskEvents.GROUP_PD_UPDATE_MEMBER_NAME_NOTIFY)
	private TaskProducer<PdUpdateGroupMemberNameNotifyArgs> pdUpdateGroupMemberNameNotifyTask;
	@TaskEvent(GroupTaskEvents.GROUP_PD_UPDATE_NAME_NOTIFY)
	private TaskProducer<PdUpdateGroupNameNotifyArgs> pdUpdateGroupNameNotifyTask;


	@ServiceSetter
	private GroupCacheManager groupCache;

	@ServiceSetter
	private FxDataValidateService dataValidateService;

	@FieldSetter("${FX_DATA_VALIDATE}")
	private String fxdataValidate;

	@TaskEvent(GroupTaskEvents.GROUP_INVITE)
	private TaskProducer<GroupInviteArgs> outterGroupInviteTask;

	@ServiceSetter
	private GroupListVersionCacheManager groupListVersionCacheManager;

	@Override
	public void createGroup(InteropCreateGroupArgs args) {
		//更新缓存, 下发给群主通知
		LOGGER.info(String.format("fx createGroup args=%s", args.toString()));

		GroupIndex groupIndex = null;
		GroupInfo groupInfo = null;
//		if (!checkCache(args.getGroupId())) {
//			return;
//		}
		try {
			validateFxData(args.getGroupId());
			groupCache.clearGroup(args.getGroupId());
			groupIndex = groupIndexService.getGroupById(args.getGroupId());

			if (groupIndex != null) {
				// 通过dao 构造缓存.
				groupInfo = groupService.getGroupInfo(groupIndex);
			}
		} catch (Exception e) {
			LOGGER.error(String.format("getGroup  err"), e);
		}
		if (groupIndex == null || groupInfo == null) {
			LOGGER.error(String.format("FxCreateGroup err groupIndex or groupInfo is null args=%s", args.toJsonObject()));
		}
		//TODO 1 首先创建群,然后返回结果, 这里需要调整顺序
		// 1. 检查群是否存在.
		MobileNo referByeMobileNo = MobileNo.parseFrom(args.getFromMobileNo());
		int grpListVer = groupListVersionCacheManager.incGrpListVer(referByeMobileNo);
		// 飞信过来的 就不检查人是否打到群上限.或者没创建群的权限
//		if (!userGroupListDao.canCreateGroup(fromMobileNo)) {
//			throw new GroupException(GroupError.SERVER_ERROR);
//		}
		// And PC send GroupList Notify
		AndPcGroupListNotifyArgs andPcGroupListNotifyArgs = new AndPcGroupListNotifyArgs();
		andPcGroupListNotifyArgs.setVersion(grpListVer);
		andPcGroupListNotifyArgs.setNotifyMember(referByeMobileNo);
		grouplistNotifyToPcTask.produce(andPcGroupListNotifyArgs);

		//如果是PC 客户端创建,需要给自己的手机终端发一个激活的INVITE 信令.
		GroupMessageArgs groupMessageArgs = new GroupMessageArgs();
		groupMessageArgs.setGroupId(groupInfo.getGroupId());
		groupMessageArgs.setToMobile(referByeMobileNo); // 接受者为自己
		groupMessageArgs.setDomain(GroupConfiguration.INSTANCE.getGroupDomain());
		groupMessageArgs.setConversationId(groupInfo.getConversationId());
		groupMessageArgs.setSubject(groupInfo.getSubject());
		groupMessageArgs.setIsOnlyActiveOfflineMsg(true); // 设置为仅仅激活群. 复用用激活离线消息下发的方式吧.
		groupTerminalService.sendTextMessage(groupMessageArgs);

		final GroupInfo groupInfoFinal = groupInfo;
		if (args.getMembers() != null && args.getMembers().size() > 0) {
			args.getMembers().forEach(e -> {
				try {
					MobileNo mobileNo = MobileNo.parseFrom(e);
					inviteGroupMember(groupInfoFinal, referByeMobileNo, mobileNo);
				} catch (Exception ee) {
					LOGGER.error(String.format("fxCreateGroup Invite MemberError createArgs=%s ,Member=%s", args, toString()), e);
				}

			});
		} else {
			LOGGER.info(String.format("no members args =%s", args));
		}

	}

	private boolean checkCache(int groupId) {
		try {
			return groupCache.getGroupInfo(groupId) != null;
		} catch (Exception e) {
			LOGGER.error("getGroupCache occur error :{}", e);
			return false;
		}
	}


	/**
	 * 邀请群成员加入,需要给被邀请者发通知
	 *
	 * @param args
	 */
	@Override
	public void inviteMemberJoinGroup(InteropGroupInviteArgs args) {
		LOGGER.info(String.format("inviteMemberJoinGroup args=%s", args.toString()));
		GroupIndex groupIndex = null;
		GroupInfo groupInfo = null;
		if (!checkCache(args.getGroupId())) {
			return;
		}
		try {
			validateFxData(args.getGroupId());
			groupCache.clearGroup(args.getGroupId());
			groupIndex = groupIndexService.getGroupById(args.getGroupId());
			if (groupIndex != null) {
				// 通过dao 构造缓存.
				groupInfo = groupService.getGroupInfo(groupIndex);
			}
		} catch (Exception e) {
			LOGGER.error(String.format(" inviteMemberJoinGroup args=%s", args), e);

		}
		if (groupIndex == null || groupInfo == null) {
			LOGGER.error(String.format("inviteMemberJoinGroup err groupIndex or groupInfo is null args=%s", args.toJsonObject()));
		}

		final GroupInfo groupInfoFinal = groupInfo;
		MobileNo referByeMobileNo = MobileNo.parseFrom(args.getReferBy());
		if (args.getMembers() != null && args.getMembers().size() > 0) {
			args.getMembers().forEach(e -> {
				try {
					MobileNo mobileNo = MobileNo.parseFrom(e);
					inviteGroupMember(groupInfoFinal, referByeMobileNo, mobileNo);
				} catch (Exception ee) {
					LOGGER.error(String.format("inviteMemberJoinGroup Invite MemberError referBy=%s createArgs=%s ,Member=%s", referByeMobileNo, args, toString()), e);
				}
			});
		} else {
			LOGGER.info(String.format("no members args =%s", args));
		}


	}

	@Override
	public void acceptGroupInvite(InteropAcceptGroupInviteArgs args) {
		LOGGER.info(String.format("acceptGroupInvite args=%s", args.toString()));
		if (!checkCache(args.getGroupId())) {
			return;
		}
		GroupInfo groupInfo = null;
		try {
			validateFxData(args.getGroupId());
			groupCache.clearGroup(args.getGroupId());
			GroupIndex groupIndex = groupIndexService.getGroupById(args.getGroupId());
			if (groupIndex != null) {
				// 通过dao 构造缓存.
				groupInfo = groupService.getGroupInfo(groupIndex);
			}
		} catch (Exception e) {
			LOGGER.error(String.format("FxCreateGroup err args=%s", args), e);
			return;
		}
		try {
			if (groupInfo == null) {
				LOGGER.error(String.format("acceptGroupInvite err groupIndex or groupInfo is null args=%s", args.toJsonObject()));
				return;
			}
			MobileNo toMobile = MobileNo.parseFrom(args.getUser());

			NotifyMembersHelper.notifyGroupInfoToMembers(infoNotifyTask, subscriptionManager, groupInfo);
			NotifyMembersHelper.notifyGroupListToMember(listNotifyTask, subscriptionManager, groupInfo, toMobile);
			MobileNo inviterMobile = MobileNo.parseFrom(args.getReferBy());
//			for (GroupMember member : groupInfo.getMembers()) {
//				if (member.getMobileNo().equals(toMobile)) {
//					inviterMobile = member.getReferBy();
//					break;
//				}
//			}

			// 飞信同意后，给手机下发cancle，复用inviteTask
			GroupInviteArgs a = new GroupInviteArgs();
			a.setReferredTo(toMobile);
			a.setGroupId(groupInfo.getGroupId());
			a.setCancel(true);
			outterGroupInviteTask.produce(a);

			int grpListVer = groupListVersionCacheManager.incGrpListVer(toMobile);
			if (inviterMobile != null) {// TODO 有必要这么干么? 是不是要验证一下
				PdNotifyMembersHelper.groupInviteReplyMessage(pdGroupInviteReplyMessageTask,
						groupInfo.getGroupId(),
						GroupConfiguration.INSTANCE.getGroupDomain(),
						groupInfo.getSubject(),
						groupInfo.getGroupAdmin(),
						groupInfo.getConversationId(),
						inviterMobile,
						toMobile,
						"yes");
			}

			// TODO PD
			PdNotifyMembersHelper.groupInviteReplyNotify(pdGroupInviteReplyNotifyTask,
					subscriptionManager,
					null,
					groupInfo.getGroupId(),
					GroupConfiguration.INSTANCE.getGroupDomain(),
					"",
					"",
					toMobile,
					"");

			// TODO And PC Server
			AndPcGroupMemberInfoNotifyArgs andPcGroupMemberInfoNotifyArgs = new AndPcGroupMemberInfoNotifyArgs();
			GroupMemberInfoArgs groupMemberInfo = new GroupMemberInfoArgs();
			List<MobileNo> notifyMembers = new ArrayList<>();
			groupInfo.getMembers().forEach(groupMember -> {
				if (groupMember.getIdentity() != 61) {
					notifyMembers.add(groupMember.getMobileNo());
				}
				if (groupMember.getMobileNo().equals(toMobile)) {
					groupMemberInfo.setIdentity(groupMember.getIdentity());
					groupMemberInfo.setMobileNo(groupMember.getMobileNo());
					groupMemberInfo.setNickName(StringUtils.isNullOrEmpty(groupMember.getDisplayname()) ? groupMember.getMobileNo().getMobile() : groupMember.getDisplayname());
					groupMemberInfo.setStatus(2);
				}
			});
			andPcGroupMemberInfoNotifyArgs.setNotifyMemberList(notifyMembers);
			andPcGroupMemberInfoNotifyArgs.setGroupId(groupInfo.getGroupId());
			andPcGroupMemberInfoNotifyArgs.setPushMode(2);
			List<GroupMemberInfoArgs> members = new ArrayList<>();
			members.add(groupMemberInfo);
			andPcGroupMemberInfoNotifyArgs.setMemberInfoList(members);
			groupMemberInfoNotifyToPcTask.produce(andPcGroupMemberInfoNotifyArgs);

			AndPcGroupListNotifyArgs andPcGroupListNotifyArgs = new AndPcGroupListNotifyArgs();
			andPcGroupListNotifyArgs.setNotifyMember(toMobile);
			andPcGroupListNotifyArgs.setVersion(grpListVer);
			grouplistNotifyToPcTask.produce(andPcGroupListNotifyArgs);
		} catch (Exception e) {
			LOGGER.error(String.format(" acceptGroupInvite invoke And PC Server error args=%s", args), e);

		}

	}


	@Override
	public void kickGroupMember(InteropKickGroupMemberArgs args) {
		LOGGER.info(String.format("kickGroupMember args=%s", args.toString()));
		if (!checkCache(args.getGroupId())) {
			return;
		}
		GroupInfo groupInfo = null;
		try {
			GroupIndex groupIndex = groupIndexService.getGroupById(args.getGroupId());
			if (groupIndex != null) {
				// 通过dao 构造缓存.
				groupInfo = groupService.getGroupInfo(groupIndex);
			}
		} catch (Exception e) {
			LOGGER.error(String.format("kickGroupMember err args=%s", args.toJsonObject()));
			return;
		}
		LOGGER.info("FX kickGroupMember groupInfo : {}", groupInfo.toJsonObject());

		delMember(groupInfo, MobileNo.parseFrom(args.getUser()), "Booted");
		validateFxData(args.getGroupId());

	}


	@Override
	public void quitGroup(InteropQuitGroupArgs args) {

		LOGGER.info(String.format("quitGroup args=%s", args.toString()));
		if (!checkCache(args.getGroupId())) {
			return;
		}
		GroupInfo info = null;
		try {
//			validateFxData(args.getGroupId());
			GroupIndex index = groupIndexService.getGroupById(args.getGroupId());
			if (index != null) {
				// 通过dao 构造缓存.
				info = groupService.getGroupInfo(index);
			}
		} catch (Exception e) {
			LOGGER.error(String.format("quitGroup err args=%s", args.toJsonObject()));
			return;

		}
		if (info == null) {
			LOGGER.error(String.format(" quitError groupInfo is null args=%s", args.toJsonObject()));
			return;
		}
		LOGGER.info("FX quitGroup groupInfo : {}", info.toJsonObject());
		delMember(info, MobileNo.parseFrom(args.getUser()), "Call completed");
		validateFxData(args.getGroupId());
	}


	@Override
	public void dismissGroup(InteropDismissGroupArgs args) {
		LOGGER.info(String.format("dismissGroup args=%s", args.toString()));
		if (!checkCache(args.getGroupId())) {
			return;
		}
		GroupIndex index = null;
		GroupInfo info = null;
		//TODO 这里需要注意,如果是讨论组,则解散的referby 为-1 . 现在虽然用不到,但是难说以后会干点什么. 

		try {
//			index = groupIndexService.getGroupById(args.getGroupId());
			index = new GroupIndex(args.getGroupId(), 0);
			if (index != null) {
				// 通过dao 构造缓存.
				info = groupService.getGroupInfo(index);
			}
		} catch (Exception e) {
			LOGGER.error(String.format("dismissGroup err args=%s", args.toJsonObject()));
			return;
		}
		if (index == null || info == null) {
			LOGGER.error(String.format("dismissGroup err groupIndex or groupInfo is null args=%s", args.toJsonObject()));
//			return;
		}


		List<GroupMemberSubscription> subs = subscriptionManager.getMemberConferenceSubscriptions(args.getGroupId());
		if (subs != null)
			for (GroupMemberSubscription sub : subs) {
				// 只针对本类型的群订阅执行
				if (!sub.getSubType().equals(GroupSubscribeType.AD_GROUP)) {
					continue;
				}
				// 先给被踢的人 发一个bye,
				GroupByeArgs byeArgs = new GroupByeArgs();
				byeArgs.setGroupId(args.getGroupId());
				byeArgs.setCause(200);
				byeArgs.setToMember(sub.getUserMobile());
				byeArgs.setText("Call Completed"); // 解散群 Call Completed

				// 获取用户所在域
				SipURI uri = (SipURI) enumService.getSipURI(sub.getUserMobile());
				if (uri == null) {
					LOGGER.error(String.format("Fx inviteGroupMember error Uri is null groupId=%s, toMobile=%s", info.getGroupId(), sub.getUserMobile()));
					continue;
				} else {
					groupTerminalService.kickMember(byeArgs);
				}
			}
		try {
			// TODO And PC Server
			AndPcDismissGroupNotifyArgs andPcDismissGroupNotifyArgs = new AndPcDismissGroupNotifyArgs();
			andPcDismissGroupNotifyArgs.setGroupId(args.getGroupId());
			List<MobileNo> notifyMembers = new ArrayList<>();
			if (info != null)
				info.getMembers().forEach(groupMember -> {
					if (groupMember.getIdentity() != 61) {
						notifyMembers.add(groupMember.getMobileNo());
					}
				});
			andPcDismissGroupNotifyArgs.setNotifyMemberList(notifyMembers);
			dismissGroupNotifyToPcTask.produce(andPcDismissGroupNotifyArgs);
		} catch (Exception ex) {
			LOGGER.error("GroupByeTask or dismissGroupNotifyToPcTask", ex);
		}

		validateFxData(args.getGroupId());

	}

	@Override
	public void changeAdmin(InteropChangeAdminArgs args) {
		LOGGER.info(String.format("changeAdmin args=%s", args.toString()));
		if (!checkCache(args.getGroupId())) {
			return;
		}
		GroupIndex groupIndex = null;
		GroupInfo info = null;
		try {
			validateFxData(args.getGroupId());
			groupCache.clearGroup(args.getGroupId());
			groupIndex = groupIndexService.getGroupById(args.getGroupId());
			if (groupIndex != null) {
				// 通过dao 构造缓存.
				info = groupService.getGroupInfo(groupIndex);
			}
		} catch (Exception e) {
			LOGGER.error(String.format("changeAdmin err"));
		}
		try {
			if (groupIndex == null || info == null) {
				LOGGER.error(String.format("changeAdmin err groupIndex or groupInfo is null args=%s", args.toJsonObject()));
				return;
			}
			MobileNo referBy = MobileNo.parseFrom(args.getReferBy());
			MobileNo referTo = MobileNo.parseFrom(args.getReferTo());
			NotifyMembersHelper.notifyGroupInfoToMembers(infoNotifyTask, subscriptionManager, info);
			PdNotifyMembersHelper.changeGroupOwnerNotify(pdChangeGroupOwnerNotifyTask,
					subscriptionManager,
					null,
					info.getGroupId(),
					GroupConfiguration.INSTANCE.getGroupDomain(),
					"",
					"",
					referBy,
					referTo);

			// TODO And PC Server
			AndPcGroupMemberInfoNotifyArgs andPcGroupMemberInfoNotifyArgs = new AndPcGroupMemberInfoNotifyArgs();
			GroupMemberInfoArgs referByMemberinfo = new GroupMemberInfoArgs();
			GroupMemberInfoArgs referToMemberinfo = new GroupMemberInfoArgs();
			List<MobileNo> notifyMembers = new ArrayList<>();
			info.getMembers().forEach(groupMember -> {
				if (groupMember.getIdentity() != 61) {
					notifyMembers.add(groupMember.getMobileNo());
				}
				if (groupMember.getMobileNo().equals(referBy)) {
					referByMemberinfo.setIdentity(groupMember.getIdentity());
					referByMemberinfo.setMobileNo(groupMember.getMobileNo());
					referByMemberinfo.setNickName(StringUtils.isNullOrEmpty(groupMember.getDisplayname()) ? groupMember.getMobileNo().getMobile() : groupMember.getDisplayname());
					referByMemberinfo.setStatus(2);
				}
				if (groupMember.getMobileNo().equals(referTo)) {
					referToMemberinfo.setIdentity(groupMember.getIdentity());
					referToMemberinfo.setMobileNo(groupMember.getMobileNo());
					referToMemberinfo.setNickName(StringUtils.isNullOrEmpty(groupMember.getDisplayname()) ? groupMember.getMobileNo().getMobile() : groupMember.getDisplayname());
					referToMemberinfo.setStatus(2);
				}
			});
			andPcGroupMemberInfoNotifyArgs.setNotifyMemberList(notifyMembers);
			andPcGroupMemberInfoNotifyArgs.setGroupId(info.getGroupId());
			andPcGroupMemberInfoNotifyArgs.setPushMode(2);
			List<GroupMemberInfoArgs> members = new ArrayList<>();
			members.add(referByMemberinfo);
			members.add(referToMemberinfo);
			andPcGroupMemberInfoNotifyArgs.setMemberInfoList(members);
			groupMemberInfoNotifyToPcTask.produce(andPcGroupMemberInfoNotifyArgs);

		} catch (Exception ex) {
			LOGGER.error(String.format("ChangeAdminTask or groupMemberInfoNotifyToPcTask "), ex);
		}
	}

	@Override
	public void modifyGroupName(InteropModifyGroupNameArgs args) {
		 /*
		 * 检查群是否存在, 检查发起人是否为群主. 检查群名称是否合法.
         */
		LOGGER.info(String.format("modifyGroupName args=%s", args.toString()));
		if (!checkCache(args.getGroupId())) {
			return;
		}

		GroupInfo groupInfo = null;
		GroupIndex groupIndex = null;
		try {
			validateFxData(args.getGroupId());
//			groupCache.clearGroup(args.getGroupId());
			groupIndex = groupIndexService.getGroupById(args.getGroupId());
			if (groupIndex != null) {
				// 通过dao 构造缓存.
				groupInfo = groupService.getGroupInfo(groupIndex);
			}
		} catch (Exception e) {
			LOGGER.error(String.format("modifyGroupName err"));
		}

		if (null == groupIndex || null == groupInfo) {
			LOGGER.error(String.format("modifyGroupName err groupIndex or groupInfo is null args=%s", args.toJsonObject()));
			return;
		}
		try {
			String subject = args.getSuject();
			NotifyMembersHelper.notifyGroupInfoToMembers(infoNotifyTask, subscriptionManager, groupInfo);
			// T端Group做PreDefined逻辑
			PdNotifyMembersHelper.updateGroupNameNotify(pdUpdateGroupNameNotifyTask,
					subscriptionManager,
					null,
					groupInfo.getGroupId(),
					GroupConfiguration.INSTANCE.getGroupDomain(),
					"",
					"",
					subject);


			// TODO And PC Server
			AndPcGroupInfoNotifyArgs andPcGroupInfoNotifyArgs = new AndPcGroupInfoNotifyArgs();
			andPcGroupInfoNotifyArgs.setGroupid(groupInfo.getGroupId());
			andPcGroupInfoNotifyArgs.setSubject(subject);
			List<MobileNo> notifyMembers = new ArrayList<>();
			groupInfo.getMembers().forEach(groupMember -> {
				if (groupMember.getIdentity() != 61) {
					notifyMembers.add(groupMember.getMobileNo());
				}
			});
			andPcGroupInfoNotifyArgs.setNotifyMemberList(notifyMembers);
			groupInfoNotifyToPcTask.produce(andPcGroupInfoNotifyArgs);

		} catch (Exception ex) {
			LOGGER.error("AndPC ModifyGroupNameTask or groupInfoNotifyToPcTask ", ex);
		}
	}

	@Override
	public void modifyGroupCard(InteropModifyGroupCardArgs args) {
		LOGGER.info(String.format("modifyGroupCard args=%s", args.toString()));
		if (!checkCache(args.getGroupId())) {
			return;
		}
		GroupInfo groupInfo = null;
		GroupIndex groupIndex = null;
		try {
			validateFxData(args.getGroupId());
			groupCache.clearGroup(args.getGroupId());
			groupIndex = groupIndexService.getGroupById(args.getGroupId());
			if (groupIndex != null) {
				// 通过dao 构造缓存.
				groupInfo = groupService.getGroupInfo(groupIndex);
			}
		} catch (Exception e) {
			LOGGER.error(String.format("modifyGroupCard err  args=%s", args.toJsonObject()));
			return;
		}
		try {
			if (null == groupIndex || null == groupInfo) {
				LOGGER.error(String.format("modifyGroupCard err groupIndex or groupInfo is null args=%s", args.toJsonObject()));
				return;
			}
			MobileNo mobileNo = MobileNo.parseFrom(args.getReferBy());
			String nickName = args.getNickName();
			NotifyMembersHelper.notifyGroupInfoToMembers(infoNotifyTask, subscriptionManager, groupInfo);
			PdNotifyMembersHelper.updateGroupMemberNameNotify(pdUpdateGroupMemberNameNotifyTask,
					subscriptionManager,
					null,
					groupInfo.getGroupId(),
					GroupConfiguration.INSTANCE.getGroupDomain(),
					"",
					"",
					mobileNo,
					nickName);

			// TODO And PC Server
			AndPcGroupMemberInfoNotifyArgs andPcGroupMemberInfoNotifyArgs = new AndPcGroupMemberInfoNotifyArgs();
			GroupMemberInfoArgs groupMemberInfo = new GroupMemberInfoArgs();
			List<MobileNo> notifyMembers = new ArrayList<>();
			groupInfo.getMembers().forEach(groupMember -> {
				if (groupMember.getIdentity() != 61) {
					notifyMembers.add(groupMember.getMobileNo());
				}
				if (groupMember.getMobileNo().equals(mobileNo)) {
					groupMemberInfo.setIdentity(groupMember.getIdentity());
					groupMemberInfo.setMobileNo(groupMember.getMobileNo());
					groupMemberInfo.setNickName(StringUtils.isNullOrEmpty(groupMember.getDisplayname()) ? groupMember.getMobileNo().getMobile() : groupMember.getDisplayname());
					groupMemberInfo.setStatus(2);
				}
			});
			andPcGroupMemberInfoNotifyArgs.setNotifyMemberList(notifyMembers);
			andPcGroupMemberInfoNotifyArgs.setGroupId(groupInfo.getGroupId());
			andPcGroupMemberInfoNotifyArgs.setPushMode(2);
			List<GroupMemberInfoArgs> members = new ArrayList<>();
			members.add(groupMemberInfo);
			andPcGroupMemberInfoNotifyArgs.setMemberInfoList(members);
			groupMemberInfoNotifyToPcTask.produce(andPcGroupMemberInfoNotifyArgs);
		} catch (Exception ex) {
			LOGGER.error("andPC   groupMemberInfoNotifyToPcTask  error", ex);
		}


	}


	private void delMember(GroupInfo info, MobileNo referBy, String toCaseText) {
		try {
			//TODO 需要验证是不是本群成员
			NotifyMembersHelper.notifyGroupInfoToMembers(infoNotifyTask, subscriptionManager, info, null, GroupInfoNotifyType.DELETED, false, referBy);
			NotifyMembersHelper.notifyGroupListToMember(listNotifyTask, subscriptionManager, info, referBy);
			PdNotifyMembersHelper.removeGroupMemberNotify(pdRemoveGroupMemberNotifyTask,
					subscriptionManager,
					referBy,
					info.getGroupId(),
					GroupConfiguration.INSTANCE.getGroupDomain(),
					"",
					"",
					referBy);
			GroupByeArgs byeArgs = new GroupByeArgs();
			byeArgs.setText(toCaseText);
			byeArgs.setCause(200);
			byeArgs.setGroupId(info.getGroupId());
			byeArgs.setToMember(referBy);
			byeTask.produce(byeArgs);
			subscriptionManager.unsubscribeConference(info.getGroupId(), referBy);
			subscriptionManager.unsubscribeGroupList(referBy);
			int grpListVer = groupListVersionCacheManager.incGrpListVer(referBy);
			// TODO And PC Server
			AndPcGroupMemberInfoNotifyArgs andPcGroupMemberInfoNotifyArgs = new AndPcGroupMemberInfoNotifyArgs();
			GroupMemberInfoArgs groupMemberInfo = new GroupMemberInfoArgs();
			List<MobileNo> notifyMembers = new ArrayList<>();
			info.getMembers().forEach(groupMember -> {
				if (groupMember.getIdentity() != 61) {
					notifyMembers.add(groupMember.getMobileNo());
				}
				if (groupMember.getMobileNo().equals(referBy)) {
					groupMemberInfo.setIdentity(groupMember.getIdentity());
					groupMemberInfo.setMobileNo(groupMember.getMobileNo());
					groupMemberInfo.setNickName(StringUtils.isNullOrEmpty(groupMember.getDisplayname()) ? groupMember.getMobileNo().getMobile() : groupMember.getDisplayname());
					groupMemberInfo.setStatus(4);
				}
			});
			andPcGroupMemberInfoNotifyArgs.setNotifyMemberList(notifyMembers);
			andPcGroupMemberInfoNotifyArgs.setGroupId(info.getGroupId());
			andPcGroupMemberInfoNotifyArgs.setPushMode(2);
			List<GroupMemberInfoArgs> members = new ArrayList<>();
			members.add(groupMemberInfo);
			andPcGroupMemberInfoNotifyArgs.setMemberInfoList(members);
			groupMemberInfoNotifyToPcTask.produce(andPcGroupMemberInfoNotifyArgs);

			AndPcGroupListNotifyArgs andPcGroupListNotifyArgs = new AndPcGroupListNotifyArgs();
			andPcGroupListNotifyArgs.setNotifyMember(referBy);
			andPcGroupListNotifyArgs.setVersion(grpListVer); // TODO
			grouplistNotifyToPcTask.produce(andPcGroupListNotifyArgs);


		} catch (Exception ex) {
			LOGGER.error("GroupByeTask or groupMemberInfoNotifyToPcTask  ", ex);
		}
	}

	private void inviteGroupMember(GroupInfo info, MobileNo referBy, MobileNo toMobile) throws Exception {
		//TODO: 处理超限，逗你玩模式等

		if (toMobile.equals(info.getGroupAdmin())) return; // 不能邀请管理
		GroupInviteArgs entity = new GroupInviteArgs();
		entity.setConversationId(info.getConversationId());
		entity.setGroupId(info.getGroupId());
		entity.setSubject(info.getSubject());
		entity.setDomain(GroupConfiguration.INSTANCE.getGroupDomain());
		entity.setReferredBy(referBy);
		entity.setReferredTo(toMobile);
		// 查询目标用户所在域
		SipURI uri = (SipURI) enumService.getSipURI(toMobile);
		if (uri == null) {
			LOGGER.error(String.format("Fx inviteGroupMember error Uri is null groupId=%s, toMobile=%s", info.getGroupId(), toMobile));
		} else {
			// 无所谓本域外域, 都是一个task , 在最终创建dialog 的时候实现域的区分
//			boolean isLocal = userLocatorService.lookup(toMobile).getType().equals(UserType.INNER);
//			if (isLocal) {
			// 设计为GroupTerminal的实现
			groupTerminalService.inviteJoinGroup(entity);
//			} else {
//				// TODO 外域逻辑
//				outterGroupInviteTask.produce(entity);
//			}
		}
		try {
			// TODO And PC Server
			AndPcGroupInviteNotifyArgs andPcGroupInviteNotifyArgs = new AndPcGroupInviteNotifyArgs();
			andPcGroupInviteNotifyArgs.setSubject(info.getSubject());
			andPcGroupInviteNotifyArgs.setConversationId(info.getConversationId());
			andPcGroupInviteNotifyArgs.setDomain(GroupConfiguration.INSTANCE.getGroupDomain());
			andPcGroupInviteNotifyArgs.setGroupId(info.getGroupId());
			andPcGroupInviteNotifyArgs.setReferByMobileNo(referBy);
			andPcGroupInviteNotifyArgs.setReferToMobileNo(toMobile);
			info.getMembers().forEach(groupMember -> {
				if (groupMember.getMobileNo().equals(referBy)) {
					andPcGroupInviteNotifyArgs.setReferByName(groupMember.getDisplayname().equals("") ? referBy.getMobile() : groupMember.getDisplayname());
				} else {
					return;
				}
			});
			groupInviteNotifyToPcTask.produce(andPcGroupInviteNotifyArgs);
		} catch (Exception ex) {
			LOGGER.error("invite member, r pc server error ", ex);
		}
	}


	/**
	 * 验证数据, 目前只修正管理员.
	 *
	 * @param groupId
	 */
	private void validateFxData(int groupId) {
		try {
			if ("true".equals(fxdataValidate)) {
				groupCache.clearGroup(groupId);
				dataValidateService.electionAdmin(groupId);
			}
		} catch (Exception e) {
			LOGGER.error(String.format("validateFxData error, groupId=%s", groupId), e);
		}
	}
}
